/****************************************************************************/
/*                                                                          */
/*   FILE:    session.c	                                                    */
/*   DATE:    30/06/97                                                      */
/*   PURPOSE: DVB-CI Session layer - entry point into SESS task          	*/
/*			- Initialization Module				    					    */
/*			- Main Module					    							*/
/*		    - Ending Module												    */
/*   TAB STOPS : 4															*/
/*   HISTORY:				                                    			*/
/*   Version	Date	  	    Written by	     Notes	    	   			*/
/*	 1.0	    30/06/1997      SCM              Initial implementation 	*/
/*	 1.03		19/09/1997		SCM         	 ssnb assign modification	*/
/*				- SESS_AllocSsnbIndex :the ssnb are between 0 and MAXSSNB			*/
/*				- SESS_RoutSsnb :the rssnb are between MAXSSNB and MAXSSNB*2*/
/*       1.05  28/12/1998  In function int SESS_Init() first test modified: */
/*               if (ITC_Init(SESS) = 0)  becomes  if (ITC_Init(SESS) <= 0) */
/*                                                                    	    */
/*--------------------------------------------------------------------------*/
/*   GENERAL COMMENTS                                                 	    */
/*									    									*/
/****************************************************************************/
#include <stdio.h>
#include <memory.h>
#include "sm_trace.h"
#include "itc.h"
#include "session.h"

/*--------------------------------------------------------------------------*/
/* Global Variables		                                            		*/
/*--------------------------------------------------------------------------*/
sess_t 			g_ses_tab_ssnb[MAXSSNB];   	/* ssnb table   								*/
static short 	s_sesCount;					/* number of established sessions				*/

/*--------------------------------------------------------------------------*/
/* Local Variables		                                            		*/
/*--------------------------------------------------------------------------*/
static unsigned short s_ses_timer_ids[MAXSSNB]; /* unique TIMESESS timer ident */


/* ======================================================================== */
/* NAME : session							    							*/
/* 									    									*/
/* DESCRIPTION : entry point into SESS task :				    			*/
/*		 - Initialization Module				   							*/
/*		 - Main Module						    							*/
/*		 - Ending Module				         							*/
/*	The Main Module is an infinite loop :								    */
/*		 - wait events (messages from TRANS task or RM task,   				*/
/*		   internal timeouts)					    						*/
/*		 - read the first received event  			   						*/
/*		 - call the Transport State Diagram SESS_State	          			*/
/*	                                                                  		*/
/* 									 										*/
/* INPUT PARAMETERS :							    						*/
/*									    									*/
/* OUTPUT PARAMETERS :							  							*/
/*									   										*/
/* RETURN CODE								   								*/
/*									   										*/
/* ======================================================================== */
int session(void* param)
{
	int			rc=0;
	xmsg_t		xmsg;

	SM_TRACE_CRITICAL(TRMOD_SESS, "session() - entry, param=0x%08X\r\n", param);

	/* Call the Initialization Module */
	if (! SESS_Init())
	{
		SM_TRACE_ERROR(TRMOD_SESS, "session() - sess init failed\r\n");
		rc = -1; /* error while Initialization */
	}

	/* Main Module */
	/* =========== */
	while(rc == 0)		/* infinite loop */
	{
		SM_TRACE_INFO(TRMOD_TRANS, "session() - wait event infinite...\r\n");

		/* Blocking Wait for event */
		if (! ITC_RecvXmsg(&xmsg, ITC_INFINITE))
		{
			SM_TRACE_ERROR(TRMOD_SESS, "session() - Wait event Error in return code\r\n");
			rc = -1;
			break;
		}

		if (xmsg.m_type == XMG_EXIT)
		{
			SM_TRACE_CRITICAL(TRMOD_SESS, "session() - receive XMG_EXIT\r\n");
			break;
		}

		/* Reading the event */
		if (xmsg.m_type)
		{
			SM_TRACE_INFO(TRMOD_TRANS, "session() - received xmsg\r\n");
			/* Call the Transport State Diagram */
			SESS_State(&xmsg);
		}
		else
		{
			SM_TRACE_ERROR(TRMOD_SESS, "session() - Error in received event\r\n");
			rc = -1;
			break;
		}
	}

	/* Call the Ending Module : should never get executed */
	SESS_End();

	SM_TRACE_CRITICAL(TRMOD_SESS, "session() - return, rc=%d\r\n", rc);
	return rc;
}
/* End of Main Module */
/* ================== */


/* ======================================================================== */
/* NAME : SESS_Init							    							*/
/* 									    									*/
/* DESCRIPTION : Initialization Module					    				*/
/*		 Session variables initialization			    					*/
/*		 Session State Diagram initialization 	            				*/
/* 									    									*/
/* INPUT PARAMETERS :							    						*/
/*									    									*/
/* OUTPUT PARAMETERS :							    						*/
/*									    									*/
/* RETURN CODE :							    							*/
/*	1   	 	successful initialization			   						*/
/*  0			error while initialization			    					*/
/*									   										*/
/* ======================================================================== */
int SESS_Init(void)
{
	int i;

	SM_TRACE_ENTRY(TRMOD_SESS, "SESS_Init() - entry\r\n");

	if (ITC_Init(SESS) <= 0)
	{
		SM_TRACE_ERROR(TRMOD_SESS, "SESS_Init() - itc init failed\r\n");
		return 0;
	}

	for (i=0; i < MAXSSNB; i++)
		g_ses_tab_ssnb[i].m_state = SESS_NOT_USED;

	for (i=0; i < MAXSSNB; i++)
		s_ses_timer_ids[i] = 0;

	SM_TRACE_RETURN(TRMOD_SESS, "SESS_Init() - return 1\r\n");
	return 1;
}
/* End of Initialization Module */
/* ============================ */


/* ======================================================================== */
/* NAME : SESS_End							    							*/
/* 									    									*/
/* DESCRIPTION : Ending Module							    				*/
/* 									    									*/
/* INPUT PARAMETERS :							    						*/
/*									    									*/
/* OUTPUT PARAMETERS :							    						*/
/*									    									*/
/* RETURN CODE :							    							*/
/*									   										*/
/* ======================================================================== */
void SESS_End(void)
{
	SM_TRACE_ENTRY(TRMOD_SESS, "SESS_End() - entry\r\n");

	ITC_End();

	SM_TRACE_RETURN(TRMOD_SESS, "SESS_End() - return\r\n");
	return;
}
/* End of Initialization Module */
/* ============================ */


/* ======================================================================== */
/* NAME : SESS_State													    */
/* 									    									*/
/* DESCRIPTION : Entry point of the Session State Diagram Module			*/
/*		Read the event					       							    */
/*		Read the message if the event = XMSG		    				    */
/*		Find the current SSNB and the matching state diagram ssnbIndex 			*/
/*		Call the current transition matches the received event	   			*/
/* 									   										*/
/* INPUT PARAMETERS :							   							*/
/*	s_ses_xmsg_type provides the received event		   			*/
/*	g_ses_tab_ssnb[i].m_state gives the current state of the State Diagram  		*/
/*	for the current SSNB (ssnbIndex i)					    					*/
/*									   										*/
/* OUTPUT PARAMETERS :							    						*/
/*	g_ses_tab_ssnb[i].m_state is updated					    					*/
/*									  										*/
/* RETURN CODE :							  							    */
/*									 									    */
/* ======================================================================== */
void SESS_State(xmsg_t* pXmsg)
{
	int iRet; /* return code 			 			   */

	SM_TRACE_ENTRY(TRMOD_SESS, "SESS_State() - entry\r\n");

	iRet = 0;

	SM_TRACE_INFO(TRMOD_SESS, "SESS_State() - received %s(0x%02X)\r\n",
				XMSG_NAME(pXmsg->m_type), pXmsg->m_type);

	switch (pXmsg->m_type)
	{
    case SPDU :					/* Transport <--> Session */
		iRet = SESS_Spdu(pXmsg);
    	break;

	case APDU :					/* Session <--> RM */
		iRet = SESS_Apdu(pXmsg);
		break;

	case SS_TC_CREATED :   		/* Transport ---> Session */
		iRet = SESS_Created(pXmsg);
		break;

	case SS_TC_DELETED :		/* Transport ---> Session */
		iRet = SESS_Deleted(pXmsg);
		break;

	case RM_DELETE_TC :			/* RM ---> Session */
		iRet = SESS_RMDelete(pXmsg);
		break;

	case RM_OPEN_SS_RSP :		/* RM ---> Session */
		iRet = SESS_OpenRsp(pXmsg);
		break;

	case RM_OPEN_SS_REQ :		/* RM ---> Session */
		iRet = SESS_OpenReq(pXmsg);
		break;

	case RM_CLOSE_SS :			/* RM ---> Session */
		iRet = SESS_RMClose(pXmsg);
		break;

	case SS_TMPEND:
		iRet = SESS_Timeout(pXmsg); /* timeout for a transport protocol request */
		break;

	default :			/* unknown message */
		SM_TRACE_ERROR(TRMOD_SESS, "SESS_State() - Unknown message(0x%02X) is ignored", pXmsg->m_type);
		break;
	}

	FreeXmsg(pXmsg);

	SM_TRACE_RETURN(TRMOD_SESS, "SESS_State() - return\r\n");
	return;
}
/* End of Session State Diagram */
/* ============================ */



/* ======================================================================== */
/* NAME : SESS_Spdu								    						*/
/* 									    									*/
/* DESCRIPTION : Session State diagram : SPDU received 						*/
/*		- Find the Session Number											*/
/*		- Call the action													*/
/* 									    									*/
/* INPUT PARAMETERS :							    						*/
/*		pXmsg->m_bd.m_spdu contains the SPDU message received from TRANS Task		*/
/*									    									*/
/* OUTPUT PARAMETERS :							    						*/
/*									    									*/
/* RETURN CODE :							    							*/
/*		0 : the calling function must free the memory containing the message*/
/*		1 : the calling function do nothing 								*/
/*									   										*/
/* ======================================================================== */
int SESS_Spdu(xmsg_t* pXmsg)
{
	unsigned char spduTag;		/* SPDU type 										*/
	unsigned short ssnb;	/* session number									*/
	int ssnbIndex;			/* ssnbIndex of g_ses_tab_ssnb[] for the current session number */
	int iRet;				/* return code 			 							*/
	xpdu_t	xpdu;

	SM_TRACE_ENTRY(TRMOD_SESS, "SESS_Spdu() - entry\r\n");

	if (!SESS_XmsgDecode(pXmsg, &spduTag, &ssnb, &xpdu) || !spduTag)
	{
		SM_TRACE_ERROR(TRMOD_SESS, "SESS_Spdu() - Decode Error while decoding a SPDU\r\n");
		return 0;
	}

	if (spduTag == dutag_open_session_request)
	{
		/* try to reserve a nex ssnb entry in g_ses_tab_ssnb */
		iRet = SESS_AllocSsnbIndex(pXmsg->m_bd.m_spdu.m_tcid);
		if (iRet < 0)
		{
    		/* Send IHM_WARNING to IHM Task */
			SM_TRACE_ERROR(TRMOD_SESS, "SESS_Spdu() - No more available ssnb\r\n");
			SESS_NotOpen(pXmsg);
			return 0;
		}
		else
			ssnbIndex = iRet;		/* new ssnb ssnbIndex */
	}
	else if (spduTag == dutag_open_session_response) //add by pmy
	{
			SM_TRACE_ERROR(TRMOD_SESS, "SESS_Spdu() - open session response only for module\r\n");
			return 0;
	}
	else
	{
		/* Find the session number */
		ssnbIndex = SESS_GetSsnbIndex(ssnb);
		if (ssnbIndex < 0)
		{	/* not found : the event is ignored */

    		/* Send IHM_WARNING to IHM Task 	*/
			SM_TRACE_ERROR(TRMOD_SESS, "SESS_Spdu() - Unknown ssnb %d\r\n", ssnb);
			return 0;			/* free memory  */
		}
	}

	/* Call the transport state diagram */
	SESS_Action(ssnbIndex, pXmsg);

	/* Release the state diagram instance if the session doesn't exist */
    if (g_ses_tab_ssnb[ssnbIndex].m_state == SESS_IDLE)
	{
		SM_TRACE_ERROR(TRMOD_SESS, "SESS_Spdu() - free sess ssnbIndex\r\n");
   		SESS_FreeSsnbIndex(ssnbIndex);
	}

	SM_TRACE_RETURN(TRMOD_SESS, "SESS_Spdu() - return\r\n");
	return 0;
}


/* ======================================================================== */
/* NAME : SESS_OpenReq							    						*/
/* 									    									*/
/* DESCRIPTION : Session State diagram : RM_OPEN_SS_REQ received from RM 	*/
/*				 Task														*/
/*		- Find the session number											*/
/*		- Call the action													*/
/* 									    									*/
/* INPUT PARAMETERS :							    						*/
/*		pXmsg->m_bd.m_rm_open_ss_req contains the RM_OPEN_SS_REQ message received from 	*/
/*		RM Task																*/
/*									    									*/
/* OUTPUT PARAMETERS :							    						*/
/*									    									*/
/* RETURN CODE :							    							*/
/*		0 : the calling function must free the memory containing the message*/
/*		1 : the calling function do nothing 								*/
/*									   										*/
/* ======================================================================== */
int SESS_OpenReq(xmsg_t* pXmsg) // add by pmy
{
	int ssnbIndex;	/* ssnbIndex of g_ses_tab_ssnb[] for the current transport connection  	*/

	SM_TRACE_ENTRY(TRMOD_SESS, "SESS_OpenReq() - entry\r\n");

	/* try to reserve a nex ssnb entry in g_ses_tab_ssnb */
	ssnbIndex = SESS_AllocSsnbIndex(pXmsg->m_bd.m_rm_open_ss_req.m_tcid); /* new ssnb ssnbIndex */
	if (ssnbIndex < 0)
	{
    	/* Send IHM_WARNING to IHM Task */
		SM_TRACE_ERROR(TRMOD_SESS, "SESS_OpenReq() - No more available ssnb");
		return ssnbIndex;
	}

	g_ses_tab_ssnb[ssnbIndex].m_ssnb = 0;

	SESS_Action(ssnbIndex,pXmsg);

	/* Release the state diagram instance if the session doesn't exist */
	if (g_ses_tab_ssnb[ssnbIndex].m_state == SESS_IDLE)
	{
		SM_TRACE_ERROR(TRMOD_SESS, "SESS_OpenReq() - free session ssnbIndex\r\n");
		SESS_FreeSsnbIndex(ssnbIndex);
	}

	SM_TRACE_RETURN(TRMOD_SESS, "SESS_OpenReq() - return\r\n");
	return 0;
}


/* ======================================================================== */
/* NAME : SESS_Apdu								    						*/
/* 									    									*/
/* DESCRIPTION : Session State diagram : APDU received 						*/
/*		- Find the Session Number											*/
/*		- Call the action													*/
/* 									    									*/
/* INPUT PARAMETERS :							    						*/
/*		pXmsg->m_bd.m_apdu contains the APDU message received from RM Task			*/
/*									    									*/
/* OUTPUT PARAMETERS :							    						*/
/*									    									*/
/* RETURN CODE :							    							*/
/*		0 : the calling function must free the memory containing the message*/
/*		1 : the calling function do nothing 								*/
/*									   										*/
/* ======================================================================== */
int SESS_Apdu(xmsg_t* pXmsg)
{
	int ssnbIndex;	/* ssnbIndex of g_ses_tab_ssnb[] for the current transport connection  	*/

	SM_TRACE_ENTRY(TRMOD_SESS, "SESS_Apdu() - entry\r\n");

	/* Find the session number */
	ssnbIndex = SESS_GetSsnbIndex(pXmsg->m_bd.m_apdu.m_ssnb);
	if (ssnbIndex < 0)
	{
		SM_TRACE_ERROR(TRMOD_SESS, "SESS_Apdu() - session not found\r\n");
		/* not found : the event is ignored */

		/* Send IHM_WARNING to IHM Task */
	}
	else
	{
		/* Call the transport state diagram */
		SESS_Action(ssnbIndex,pXmsg);
	}

	/* Release the state diagram instance if the session doesn't exist */
    if (g_ses_tab_ssnb[ssnbIndex].m_state == SESS_IDLE)
	{
		SM_TRACE_ERROR(TRMOD_SESS, "SESS_Apdu() - free session ssnbIndex\r\n");
    	SESS_FreeSsnbIndex(ssnbIndex);
	}

	SM_TRACE_RETURN(TRMOD_SESS, "SESS_Apdu() - return\r\n");
	return 0;
}



/* ======================================================================== */
/* NAME : SESS_Created						    							*/
/* 									    									*/
/* DESCRIPTION : Session State Diagram : SS_TC_CREATED transition received 	*/
/*		- Create a new state diagram										*/
/*		- Call the action													*/
/*		- Update the state diagram											*/
/*									    									*/
/* INPUT PARAMETERS :							    						*/
/*		pXmsg->m_bd.m_tran_conn contains the SS_TC_CREATED message received from 		*/
/*		TRANS Task															*/
/*									    									*/
/* OUTPUT PARAMETERS :							    						*/
/*		g_ses_tab_ssnb[] updated												*/
/*									    									*/
/* RETURN CODE :							    							*/
/*		0 : the calling function must free the memory containing the message*/
/*		1 : the calling function do nothing 								*/
/*									   										*/
/* ======================================================================== */
int SESS_Created(xmsg_t* pXmsg)
{
	SM_TRACE_ENTRY(TRMOD_SESS, "SESS_Created() - entry\r\n");

	/* Foward the request to delete the transport connection to the TRANS Task */
	/* ======================================================================= */
	SESS_TCCreated(pXmsg->m_bd.m_ss_tccreated.m_tcid);

	SM_TRACE_RETURN(TRMOD_SESS, "SESS_Created() - return 1\r\n");
	return 1;
}


/* ======================================================================== */
/* NAME : SESS_Deleted							    						*/
/* 									    									*/
/* DESCRIPTION : Session State diagram : SS_TC_DELETED received from TRANS	*/
/*				 Task														*/
/*	- Find all sessions that match the disconnected module					*/
/*	- For each session :													*/
/*		call the action														*/
/*		free the state diagram												*/
/*	- Call the state diagram a last time to warn the RM Task				*/
/*	The sessions can be directly associated with the deleted tcid or		*/
/* indirectly (associated by routing : distant resources or applications	*/
/* using distant resources)													*/
/* 									    									*/
/* INPUT PARAMETERS :							    						*/
/*		pXmsg->m_bd.m_ss_tc_deleted contains the SS_TC_DELETED message received from TRANS*/
/*		Task 																*/
/*									    									*/
/* OUTPUT PARAMETERS :							    						*/
/*									    									*/
/* RETURN CODE :							    							*/
/*		0 : the calling function must free the memory containing the message*/
/*			(not used in this function)										*/
/*		1 : the calling function do nothing 								*/
/*									   										*/
/* ======================================================================== */
int SESS_Deleted(xmsg_t* pXmsg)
{
	int ssnbIndex;	/* ssnbIndex of g_ses_tab_ssnb[] for the current transport connection  	*/

	SM_TRACE_ENTRY(TRMOD_SESS, "SESS_Deleted() - entry\r\n");

	/* repeat for all sessions */
	for (ssnbIndex=0; ssnbIndex < MAXSSNB; ssnbIndex++)
	{
		if ((g_ses_tab_ssnb[ssnbIndex].m_state != SESS_NOT_USED) &&
			((g_ses_tab_ssnb[ssnbIndex].m_tcid == pXmsg->m_bd.m_ss_tc_deleted.m_tcid) ||		/* direct sessions   */
			 (g_ses_tab_ssnb[ssnbIndex].m_rtcid == pXmsg->m_bd.m_ss_tc_deleted.m_tcid)))     /* indirect sessions */
		{
			SESS_Action(ssnbIndex, pXmsg);

			/* Release the state diagram instance if the session doesn't exist */
    		if (g_ses_tab_ssnb[ssnbIndex].m_state == SESS_IDLE)
			{
				SM_TRACE_ERROR(TRMOD_SESS, "SESS_Deleted() - free session ssnbIndex\r\n");
    			SESS_FreeSsnbIndex(ssnbIndex);
			}
        }
	}

	/* Forward the deletion of the transport connection to the RM Task */
	/* =============================================================== */
	SESS_TCDeleted(pXmsg->m_bd.m_ss_tc_deleted.m_tcid);

	SM_TRACE_RETURN(TRMOD_SESS, "SESS_Deleted() - return\r\n");
	return 0;
}


/* ======================================================================== */
/* NAME : SESS_RMDelete						    							*/
/* 									    									*/
/* DESCRIPTION : Session State Diagram :RM_DELETE_TC transition received 	*/
/*									    									*/
/* INPUT PARAMETERS :							    						*/
/*		pXmsg->m_bd.m_tran_conn contains a RM_DELETE_TC message received from RM Task 	*/
/*									    									*/
/* OUTPUT PARAMETERS :							    						*/
/*		g_ses_tab_ssnb[] updated												*/
/*									    									*/
/* RETURN CODE :							    							*/
/*		0 : the calling function must free the memory containing the message*/
/*		1 : the calling function do nothing 								*/
/*									   										*/
/* ======================================================================== */
int SESS_RMDelete(xmsg_t* pXmsg)
{
	SM_TRACE_ENTRY(TRMOD_SESS, "SESS_RMDelete() - entry\r\n");

	/* Foward the request to delete the transport connection to the TRANS Task */
	/* ======================================================================= */
	SESS_DeleteTC(pXmsg->m_bd.m_rm_delete_tc.m_tcid);

	SM_TRACE_RETURN(TRMOD_SESS, "SESS_RMDelete() - return 1\r\n");
	return 1;
}




/* ======================================================================== */
/* NAME : SESS_OpenRsp							    						*/
/* 									    									*/
/* DESCRIPTION : Session State diagram : RM_OPEN_SS_RSP received from RM 	*/
/*				 Task														*/
/*		- Find the session number											*/
/*		- Call the action													*/
/* 									    									*/
/* INPUT PARAMETERS :							    						*/
/*		pXmsg->m_bd.m_rm_open_ss_rsp contains the RM_OPEN_SS_RSP message received from 	*/
/*		RM Task																*/
/*									    									*/
/* OUTPUT PARAMETERS :							    						*/
/*									    									*/
/* RETURN CODE :							    							*/
/*		0 : the calling function must free the memory containing the message*/
/*		1 : the calling function do nothing 								*/
/*									   										*/
/* ======================================================================== */
int SESS_OpenRsp(xmsg_t* pXmsg)
{
	int ssnbIndex;	/* ssnbIndex of g_ses_tab_ssnb[] for the current transport connection  	*/

	SM_TRACE_ENTRY(TRMOD_SESS, "SESS_OpenRsp() - entry\r\n");

	/* Find the Session Number */
	ssnbIndex = SESS_GetSsnbIndex(pXmsg->m_bd.m_rm_open_ss_rsp.m_ssnb);
	if (ssnbIndex < 0)
	{
		SM_TRACE_ERROR(TRMOD_SESS, "SESS_OpenRsp() - session not found\r\n");
		/* not found : the event is ignored */

		/* Send IHM_WARNING to IHM Task */
	}
	else
	{
		/* Call the transport state diagram */
		SESS_Action(ssnbIndex, pXmsg);
	}

	/* Release the state diagram instance if the session doesn't exist */
	if (g_ses_tab_ssnb[ssnbIndex].m_state == SESS_IDLE)
	{
		SM_TRACE_ERROR(TRMOD_SESS, "SESS_OpenRsp() - free session ssnbIndex,ssnbIndex=%d\r\n", ssnbIndex);
		SESS_FreeSsnbIndex(ssnbIndex);
	}

	SM_TRACE_RETURN(TRMOD_SESS, "SESS_OpenRsp() - returnd\r\n");
	return 0;
}



/* ======================================================================== */
/* NAME : SESS_RMClose							    						*/
/* 									    									*/
/* DESCRIPTION : Session State diagram : RM_CLOSE_SS received from RM Task	*/
/*		- Find the session number											*/
/*		- Call the action													*/
/* 									    									*/
/* INPUT PARAMETERS :							    						*/
/*		pXmsg->m_bd.m_rm_close_ss contains the RM_CLOSE_SS message received from RM Task 	*/
/*									    									*/
/* OUTPUT PARAMETERS :							    						*/
/*									    									*/
/* RETURN CODE :							    							*/
/*		0 : the calling function must free the memory containing the message*/
/*		1 : the calling function do nothing 								*/
/*									   										*/
/* ======================================================================== */
int SESS_RMClose(xmsg_t* pXmsg)
{
	int ssnbIndex;	/* ssnbIndex of g_ses_tab_ssnb[] for the current transport connection  	*/

	SM_TRACE_ENTRY(TRMOD_SESS, "SESS_RMClose() - entry\r\n");

	/* Find the Session Number */
	ssnbIndex = SESS_GetSsnbIndex(pXmsg->m_bd.m_rm_close_ss.m_ssnb);
	if (ssnbIndex < 0)
	{
		SM_TRACE_ERROR(TRMOD_SESS, "SESS_RMClose() - session not found\r\n");
		/* not found : the event is ignored */

		/* Send IHM_WARNING to IHM Task */
	}
	else
	{
		/* Call the transport state diagram */
		SESS_Action(ssnbIndex, pXmsg);
	}

	/* Release the state diagram instance if the session doesn't exist */
	if (g_ses_tab_ssnb[ssnbIndex].m_state == SESS_IDLE)
	{
		SM_TRACE_ERROR(TRMOD_SESS, "SESS_RMClose() - free session ssnbIndex\r\n");
		SESS_FreeSsnbIndex(ssnbIndex);
	}

	SM_TRACE_RETURN(TRMOD_SESS, "SESS_RMClose() - return\r\n");
	return 0;
}


/* ======================================================================== */
/* NAME : SESS_Timeout							    						*/
/* 									    									*/
/* DESCRIPTION : Transport State diagram : TIMEOUT received 				*/
/*		- Find the transport connection										*/
/*		- Call the action													*/
/* 									    									*/
/* INPUT PARAMETERS :							    						*/
/*		pXmsg->m_timerId contains the Timer Identifier 					  			*/
/*		Task 																*/
/*									    									*/
/* OUTPUT PARAMETERS :							    						*/
/*									    									*/
/* RETURN CODE :							    							*/
/*		0 : the calling function must free the memory containing the message*/
/*			(not used in this function)										*/
/*		1 : the calling function do nothing 								*/
/*									   										*/
/* ======================================================================== */
int SESS_Timeout(xmsg_t* pXmsg)
{
	int ssnbIndex;	/* ssnbIndex of g_ses_tab_ssnb[] for the current transport connection  	*/

	SM_TRACE_ENTRY(TRMOD_SESS, "SESS_Timeout() - entry\r\n");

	/* Find the session number */
	ssnbIndex = TRPT_GetSsnbIndexByTM(pXmsg->m_bd.m_timer.m_timerId);
	if (ssnbIndex < 0)
	{	/* not found : the event is ignored */
		SM_TRACE_ERROR(TRMOD_SESS, "SESS_Timeout() - session not found\r\n");
		/* Send IHM_WARNING to IHM Task */
		return 1;
	}

	SM_TRACE_ERROR(TRMOD_SESS, "SESS_Timeout() - kill timer,session_index=%d\r\n",ssnbIndex);
	SESS_Kill_Timer(ssnbIndex);		/* cancel the timer */

	/* Call the transport state diagram */
	SESS_Action(ssnbIndex, pXmsg);

	/* Release the state diagram instance if the session doesn't exist */
	if (g_ses_tab_ssnb[ssnbIndex].m_state == SESS_IDLE)
	{
		SM_TRACE_ERROR(TRMOD_SESS, "SESS_Timeout() - free session ssnbIndex=%d\r\n", ssnbIndex);
		SESS_FreeSsnbIndex(ssnbIndex);
	}

	SM_TRACE_RETURN(TRMOD_SESS, "SESS_Timeout() - return\r\n");
	return 0;
}



/* ======================================================================== */
/* NAME : SESS_AllocSsnbIndex					 									*/
/* 									    									*/
/* DESCRIPTION : Get a new entry in g_ses_tab_ssnb								*/
/* 									    									*/
/* INPUT PARAMETERS :							    						*/
/*		tcid : transport connection of the new session						*/
/*									 										*/
/* OUTPUT PARAMETERS :							   							*/
/*		the ssnb is assigned into g_ses_tab_ssnb  								*/
/*									    									*/
/* RETURN CODE								    							*/
/*		-1 : no more entry													*/
/*		>=0 : ssnbIndex in g_ses_tab_ssnb											*/
/*									  										*/
/* ======================================================================== */
int SESS_AllocSsnbIndex(unsigned char tcid)
{
	int ssnbIndex;				/* return code : entry found */

	SM_TRACE_ENTRY(TRMOD_SESS, "SESS_AllocSsnbIndex() - entry,tcid=%d\r\n",tcid);

	if (s_sesCount >= MAXSSNB)
	{
		SM_TRACE_ERROR(TRMOD_SESS, "SESS_AllocSsnbIndex() - too many session=%d\r\n", s_sesCount);
		return -1;						/* too many established sessions, no more entry 	*/
	}

	for (ssnbIndex=0; ssnbIndex < MAXSSNB; ssnbIndex++)
	{
		if (g_ses_tab_ssnb[ssnbIndex].m_state == SESS_NOT_USED)   /* take the first free entry, reserve it */
		{
			/* Reserve a new ssnb */
			g_ses_tab_ssnb[ssnbIndex].m_state    = SESS_IDLE;

			g_ses_tab_ssnb[ssnbIndex].m_tcid 	   = tcid;
			g_ses_tab_ssnb[ssnbIndex].m_ssnb 	   = ssnbIndex+1;	/* 0 < ssnb < MAXSSNB ; 0 is reserved */
//			g_ses_tab_ssnb[ssnbIndex].m_ssnb 	   = (ssnbIndex*2) + 1;	/* odd session number : 0 is reserved */
			/* the even ssnb are reserved for the routing ssnb on routing tcid 				  */

			g_ses_tab_ssnb[ssnbIndex].m_rtcid    = 0;
			g_ses_tab_ssnb[ssnbIndex].m_rssnb    = 0;

			g_ses_tab_ssnb[ssnbIndex].m_timerId  = 0;

			s_sesCount++;

			SM_TRACE_INFO(TRMOD_SESS, "SESS_AllocSsnbIndex() - new entry %d ssnb=%d,sscount=%d\r\n", ssnbIndex, (ssnbIndex*2)+1,s_sesCount);
			return ssnbIndex;
		}
	}

	SM_TRACE_RETURN(TRMOD_SESS, "SESS_AllocSsnbIndex() - return (-1)\r\n");
	return -1;							   			/* no more entry */
}


/* ======================================================================== */
/* NAME : SESS_FreeSsnbIndex					 								*/
/* 									    									*/
/* DESCRIPTION :Delete an entry in g_ses_tab_ssnb								*/
/* 									    									*/
/* INPUT PARAMETERS :							    						*/
/*		ssnbIndex : ssnbIndex of the entry to delete								*/
/*									 										*/
/* OUTPUT PARAMETERS :							   							*/
/*		s_sesCount is updated												*/
/*									    									*/
/* RETURN CODE								    							*/
/*		< 0 : entry not found												*/
/*		>=0 : entry deleted													*/
/*									  										*/
/* ======================================================================== */
int SESS_FreeSsnbIndex(int ssnbIndex)
{
	SM_TRACE_ENTRY(TRMOD_SESS, "SESS_FreeSsnbIndex() - entry,ssnbIndex=%d\r\n", ssnbIndex);

    if ((ssnbIndex < 0) && (ssnbIndex >= MAXSSNB))
	{
		SM_TRACE_ERROR(TRMOD_SESS, "SESS_FreeSsnbIndex() - invalid ssnbIndex=%d\r\n", ssnbIndex);
    	return -1;
	}

	SESS_Kill_Timer(ssnbIndex);							/* kill pending TIMEOUT timer */

	g_ses_tab_ssnb[ssnbIndex].m_state = SESS_NOT_USED;				/* free the entry 		*/
    s_sesCount--;

    SM_TRACE_RETURN(TRMOD_SESS, "SESS_FreeSsnbIndex() - return,ssnbIndex=%d,sscount=%d\r\n",
					ssnbIndex,s_sesCount);
	return ssnbIndex;
}


/* ======================================================================== */
/* NAME : SESS_GetSsnbIndex					 									*/
/* 									    									*/
/* DESCRIPTION : Get the ssnbIndex in g_ses_tab_ssnb								*/
/*	ssnb is looking for in ssnb and in rssnb (routing)						*/
/* 									    									*/
/* INPUT PARAMETERS :							    						*/
/*	ssnb : session number													*/
/*									 										*/
/* OUTPUT PARAMETERS :							   							*/
/*									    									*/
/* RETURN CODE								    							*/
/*		< 0 : ssnb not found in g_ses_tab_ssnb									*/
/*		>=0 : ssnbIndex in g_ses_tab_ssnb											*/
/*									  										*/
/* ======================================================================== */
int SESS_GetSsnbIndex(unsigned  short ssnb)
{
	int ssnbIndex;		/* return code : entry found */

	SM_TRACE_ENTRY(TRMOD_SESS, "SESS_GetSsnbIndex() - entry,ssnb=%d\r\n",ssnb);

	for (ssnbIndex=0; ssnbIndex < MAXSSNB; ssnbIndex++)
	{
		if ((g_ses_tab_ssnb[ssnbIndex].m_state != SESS_NOT_USED) &&
			((g_ses_tab_ssnb[ssnbIndex].m_ssnb == ssnb)
			|| (g_ses_tab_ssnb[ssnbIndex].m_rssnb == ssnb)))
		{
			return ssnbIndex;   /* matching ssnb  */
		}
	}

	SM_TRACE_RETURN(TRMOD_SESS, "SESS_GetSsnbIndex() - return (-1)\r\n");
	return -1;	   			/* ssnb not found */
}


/* ======================================================================== */
/* NAME : SESS_RoutSsnb					 									*/
/* 									    									*/
/* DESCRIPTION : Get a new session number for the routing tcid 				*/
/* 									    									*/
/* INPUT PARAMETERS :							    						*/
/*	ssnb : session number of the session (first part between the Application*/
/*			and the host)													*/
/*	rtcid: routing tcid between the host and the distant resource provider	*/
/*			module															*/
/*									 										*/
/* OUTPUT PARAMETERS :							   							*/
/*		g_ses_tab_ssnb[].m_rtcid and g_ses_tab_ssnb[].m_rssnb are updated				*/
/*									    									*/
/* RETURN CODE								    							*/
/*		 -1 : ssnb not found in g_ses_tab_ssnb									*/
/*		>=0 : ssnbIndex in g_ses_tab_ssnb											*/
/*									  										*/
/* ======================================================================== */
int SESS_RoutSsnb(unsigned short ssnb, unsigned char rtcid)
{
	int ssnbIndex;		/* return code : entry found */

	SM_TRACE_ENTRY(TRMOD_SESS, "SESS_RoutSsnb() - entry,ssnb=%d,rtcid=%d\r\n", ssnb, rtcid);

	for (ssnbIndex=0; ssnbIndex < MAXSSNB; ssnbIndex++)
	{
		if ((g_ses_tab_ssnb[ssnbIndex].m_state != SESS_NOT_USED) && (g_ses_tab_ssnb[ssnbIndex].m_ssnb == ssnb))
		{
			g_ses_tab_ssnb[ssnbIndex].m_rtcid  = rtcid;
			g_ses_tab_ssnb[ssnbIndex].m_rssnb = ssnbIndex+MAXSSNB+1;	/* MAXSSNB < rssnb MAXSSNB*2 ; 0 is reserved */
//			g_ses_tab_ssnb[ssnbIndex].m_rssnb = (ssnbIndex*2) + 2;	/* even ssnb ; 0 is reserved 	*/
			/* the odd ssnb are reserved for ssnb between the application and the host  */

			break; /* matching ssnb */
		}
	}

	if (ssnbIndex >= MAXSSNB)
	{
		SM_TRACE_ERROR(TRMOD_SESS, "SESS_RoutSsnb() - session not found\r\n");
		return -1;
	}

	SM_TRACE_RETURN(TRMOD_SESS, "SESS_RoutSsnb() - return,ssnbIndex=%d\r\n", ssnbIndex);
	return ssnbIndex;	   			/* ssnb not found */
}



/* ======================================================================== */
/* NAME : TRPT_GetSsnbIndexByTM					 								*/
/* 									    									*/
/* DESCRIPTION : Get the ssnbIndex in g_ses_tab_ssnb according to a TIMEOUT timer   */
/* 									    									*/
/* INPUT PARAMETERS :							    						*/
/*	timerId :	timer identifier											*/
/*									 										*/
/* OUTPUT PARAMETERS :							   							*/
/*									    									*/
/* RETURN CODE								    							*/
/*		< 0 : timerId not found in g_ses_tab_ssnb								*/
/*		>=0 : ssnbIndex in g_ses_tab_ssnb											*/
/*									  										*/
/* ======================================================================== */
int TRPT_GetSsnbIndexByTM(unsigned  short timerId)
{
	int ssnbIndex;		/* return code : entry found */

	SM_TRACE_ENTRY(TRMOD_SESS, "TRPT_GetSsnbIndexByTM() - entry,timerId=%d\r\n",timerId);

	for (ssnbIndex=0; ssnbIndex < MAXSSNB; ssnbIndex++)
	{
		if ((g_ses_tab_ssnb[ssnbIndex].m_state != SESS_NOT_USED) && (g_ses_tab_ssnb[ssnbIndex].m_timerId == timerId))
			return ssnbIndex;   /* matching timerId  */
	}

	SM_TRACE_RETURN(TRMOD_SESS, "TRPT_GetSsnbIndexByTM() - return (-1)\r\n");
	return -1;	   			/* timerId not found */
}


/* ======================================================================== */
/* NAME : SESS_SetTimer				 									*/
/* 									    									*/
/* DESCRIPTION : Set a unique timer identifier (base : TIMESESS)			*/
/* 									    									*/
/* INPUT PARAMETERS :							    						*/
/*	value   : value in ms													*/
/*									 										*/
/* OUTPUT PARAMETERS :							   							*/
/*									    									*/
/* RETURN CODE								    							*/
/*	   >0 : Timer identifier												*/
/*	    0 : error															*/
/*									  										*/
/* ======================================================================== */
unsigned short SESS_SetTimer(unsigned short timeout_ms)
{
	int				i;
	unsigned short	timeid;

	SM_TRACE_ENTRY(TRMOD_SESS, "SESS_SetTimer() - entry,timeout_ms=%d\r\n",timeout_ms);

	timeid = 0;
	for (i=0; i < MAXSSNB; i++)
	{
		if (!s_ses_timer_ids[i])
		{
			s_ses_timer_ids[i] = TMID_SESS_PEND_BASE+i;
			timeid = TMID_SESS_PEND_BASE+i;
			break;
		}
	}

	if (!timeid)
	{
		SM_TRACE_ERROR(TRMOD_SESS, "SESS_SetTimer() - too many sess\r\n");
		return 0;
	}

	if (ITC_SetTimer(timeid, timeout_ms) != timeid)
	{
		SM_TRACE_ERROR(TRMOD_SESS, "SESS_SetTimer() - set timer failed\r\n");
		return 0;
	}

	SM_TRACE_RETURN(TRMOD_SESS, "SESS_SetTimer() - return,timeid=%d\r\n",timeid);
	return timeid;
}


/* ======================================================================== */
/* NAME : SESS_Kill_Timer				 									*/
/* 									    									*/
/* DESCRIPTION : Kill the pending TIMEOUT timer if it exists				*/
/* 									    									*/
/* INPUT PARAMETERS :							    						*/
/*		ssnbIndex :		instance of the current state diagram					*/
/*									 										*/
/* OUTPUT PARAMETERS :							   							*/
/*									    									*/
/* RETURN CODE								    							*/
/*		1 : Success															*/
/*		0 : Error															*/
/*									  										*/
/* ======================================================================== */
void SESS_Kill_Timer(int ssnbIndex)
{
	int i;					/* loop ssnbIndex		 */

	SM_TRACE_ENTRY(TRMOD_SESS, "SESS_Kill_Timer() - entry,ssnbIndex=%d\r\n",ssnbIndex);

	if (g_ses_tab_ssnb[ssnbIndex].m_timerId != 0)
	{
		ITC_KillTimer(g_ses_tab_ssnb[ssnbIndex].m_timerId);

		/* free the unique timer identifier */
		for (i=0; i < MAXSSNB; i++)
		{
			if (s_ses_timer_ids[i] == g_ses_tab_ssnb[ssnbIndex].m_timerId)
			{
				s_ses_timer_ids[i] = 0;
				break;
			}
		}
		g_ses_tab_ssnb[ssnbIndex].m_timerId = 0;
	}

	SM_TRACE_RETURN(TRMOD_SESS, "SESS_Kill_Timer() - return\r\n");
}

